use bytes::Bytes;
use reqwest::{blocking::Response, IntoUrl};
use tokio::join;
use std::{collections::HashMap, env::{self, Vars}, fs, io::{Read, Write}, net::{TcpListener, TcpStream}, time::SystemTime};

const BD_URL: &str = "https://baidu.com";

pub fn main() {
    test_client();
}
fn my_http_server(){
    // 绑定到本地的端口 7878
    let listener = TcpListener::bind("0.0.0.0:7878").unwrap();
    println!("Listening on port 7878...");

    // 循环接受传入的连接
    for stream in listener.incoming() {
        let stream = stream.unwrap();
        handle_connection(stream);
    }
}
fn handle_connection(mut stream: TcpStream) {
    // 创建一个缓冲区来存储从流中读取的数据
    let mut buffer = [0; 512];
    stream.read(&mut buffer).unwrap();

    // 将请求转换为字符串并打印
    let request = String::from_utf8_lossy(&buffer[..]);
    println!("Request:\n {}", request);
    let addre = stream.peer_addr().unwrap();
    println!("is IPV4:{}, remote_ip: {}, local_ip:{}", addre.is_ipv4(), addre.ip(), 
            stream.local_addr().unwrap().ip());

    // 构建一个简单的 HTTP 响应
    let status_line = "HTTP/1.1 200 OK";
    let contents = include_str!("../../static/hello.html"); // 从文件中读取响应内容
    let length = contents.len();
    let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");

    // 将响应写入流中
    stream.write(response.as_bytes()).unwrap();
    stream.flush().unwrap();
}
fn str_test(){
    let s = "hello world".to_string();
    let strs: Vec<u8> = s.bytes().collect();
    let bs = Bytes::from(strs);
    let bs2 = bs.clone();


    drop(s);
    println!("bs:{:?} bs2: {:?}", bs, bs2);
    let sli = &bs2[0..5];
    println!("sli:{:?} ", String::from_utf8_lossy(sli).as_ref())
}
fn test_client(){
    let num = env::args().skip(1).next().map_or(500, |p|{
        p.parse().unwrap_or(500)
    });
    println!("num: {}", num);
    let runtime = tokio::runtime::Runtime::new().unwrap();
    // let t1 = runtime.block_on(test_client_query(num));
    let t2 = runtime.block_on(test_single_client_query(num));
    // println!("t1:{} t2:{}", t1, t2);
    println!("end..");
}
async fn test_client_query(n: i32)-> u64{
    let mut v = Vec::with_capacity(n as usize);
    let st = SystemTime::now(); //计时开始
    for i in 0..n{
        let handler =  tokio::spawn(reqwest::get(BD_URL));
        v.push(handler);
    }
    for h in v.iter_mut(){
        h.await;
    }
    let spent_time = st.elapsed().unwrap().as_secs();
    println!("spent time: {}", spent_time);
    spent_time
}
async fn test_single_client_query(n: i32)-> u64{
    let client = reqwest::ClientBuilder::new().build().unwrap();
    let mut v = Vec::with_capacity(n as usize);
    let st = SystemTime::now(); //计时开始
    for _ in 0..n{
        let client = client.clone();
        let h = tokio::spawn(async move{
            let res = client.get(BD_URL).send().await;
            match res{
                Ok(resp) => {
                    let text = resp.text().await.unwrap_or_else(|e|{
                        println!("text unwrap err: {}", e);
                        "err occur".to_string()
                    });
                    let count = text.chars().count();
                    println!("text: {}", &text[..(if count >= 100{100}else{count})]);
                },
                Err(err) => {
                    println!("err: {}", err);
                }
            }
        });
        v.push(h);
    }
    for h in v{
        if let Err(e) = h.await{
            println!("join err: {}", e);
        }
    }
    let spent_time = st.elapsed().unwrap().as_millis();
    println!("single client spent time: {}ms", spent_time);
    spent_time as u64
}
pub fn query_bytes(url: &str) ->Bytes {
    let body = reqwest::blocking
            ::get(url);
    let ar = [0];
    match body {
        Ok(res) => res.bytes().expect("query bytes failed"),
        Err(err) => {
            println!("{}", err);
            panic!("err 發生");
        }
    }
}

fn write_file(mut reader: Response) {
    let mut buf = [0u8; 1024 * 500];

    let mut file = std::fs::File::create("v.f56150——1.ts").expect("open file failed");
    loop {
        let res = reader.read(&mut buf);
        if let Ok(size) = res {
            println!("size is {}", size);
            if size <= 0 {
                break;
            }
            let handler = file.write(&buf[0..size]);
            handler.expect("写入失败");
            file.flush().expect("flush 失败");
        } else {
            panic!("读取失败");
        }
    }
}
